﻿using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq.Expressions;
using System.Reactive.Concurrency;

namespace System.Reactive.Linq
{
	public static partial class Qbservable
	{
		public static IQbservable<TResult> Generate<TState, TResult>(this IQbservableProvider provider, TState initialState, Expression<Func<TState, bool>> condition, Expression<Func<TState, TState>> iterate, Expression<Func<TState, TResult>> resultSelector)
		{
			Contract.Requires(provider != null, null, "provider != null");
			Contract.Requires(condition != null, null, "condition != null");
			Contract.Requires(iterate != null, null, "iterate != null");
			Contract.Requires(resultSelector != null, null, "resultSelector != null");
			Contract.Ensures(Contract.Result<IQbservable<TResult>>() != null, null, "Contract.Result<IQbservable<TResult>>() != null");
			return null;
		}

		public static IQbservable<TResult> Generate<TState, TResult>(this IQbservableProvider provider, TState initialState, Expression<Func<TState, bool>> condition, Expression<Func<TState, TState>> iterate, Expression<Func<TState, TResult>> resultSelector, Expression<Func<TState, DateTimeOffset>> timeSelector)
		{
			Contract.Requires(provider != null, null, "provider != null");
			Contract.Requires(condition != null, null, "condition != null");
			Contract.Requires(iterate != null, null, "iterate != null");
			Contract.Requires(resultSelector != null, null, "resultSelector != null");
			Contract.Requires(timeSelector != null, null, "timeSelector != null");
			Contract.Ensures(Contract.Result<IQbservable<TResult>>() != null, null, "Contract.Result<IQbservable<TResult>>() != null");
			return null;
		}

		public static IQbservable<TResult> Generate<TState, TResult>(this IQbservableProvider provider, TState initialState, Expression<Func<TState, bool>> condition, Expression<Func<TState, TState>> iterate, Expression<Func<TState, TResult>> resultSelector, Expression<Func<TState, TimeSpan>> timeSelector)
		{
			Contract.Requires(provider != null, null, "provider != null");
			Contract.Requires(condition != null, null, "condition != null");
			Contract.Requires(iterate != null, null, "iterate != null");
			Contract.Requires(resultSelector != null, null, "resultSelector != null");
			Contract.Requires(timeSelector != null, null, "timeSelector != null");
			Contract.Ensures(Contract.Result<IQbservable<TResult>>() != null, null, "Contract.Result<IQbservable<TResult>>() != null");
			return null;
		}

		public static IQbservable<TResult> Generate<TState, TResult>(this IQbservableProvider provider, TState initialState, Expression<Func<TState, bool>> condition, Expression<Func<TState, TState>> iterate, Expression<Func<TState, TResult>> resultSelector, IScheduler scheduler)
		{
			Contract.Requires(provider != null, null, "provider != null");
			Contract.Requires(condition != null, null, "condition != null");
			Contract.Requires(iterate != null, null, "iterate != null");
			Contract.Requires(resultSelector != null, null, "resultSelector != null");
			Contract.Requires(scheduler != null, null, "scheduler != null");
			Contract.Ensures(Contract.Result<IQbservable<TResult>>() != null, null, "Contract.Result<IQbservable<TResult>>() != null");
			return null;
		}

		public static IQbservable<TResult> Generate<TState, TResult>(this IQbservableProvider provider, TState initialState, Expression<Func<TState, bool>> condition, Expression<Func<TState, TState>> iterate, Expression<Func<TState, TResult>> resultSelector, Expression<Func<TState, DateTimeOffset>> timeSelector, IScheduler scheduler)
		{
			Contract.Requires(provider != null, null, "provider != null");
			Contract.Requires(condition != null, null, "condition != null");
			Contract.Requires(iterate != null, null, "iterate != null");
			Contract.Requires(resultSelector != null, null, "resultSelector != null");
			Contract.Requires(timeSelector != null, null, "timeSelector != null");
			Contract.Requires(scheduler != null, null, "scheduler != null");
			Contract.Ensures(Contract.Result<IQbservable<TResult>>() != null, null, "Contract.Result<IQbservable<TResult>>() != null");
			return null;
		}

		public static IQbservable<TResult> Generate<TState, TResult>(this IQbservableProvider provider, TState initialState, Expression<Func<TState, bool>> condition, Expression<Func<TState, TState>> iterate, Expression<Func<TState, TResult>> resultSelector, Expression<Func<TState, TimeSpan>> timeSelector, IScheduler scheduler)
		{
			Contract.Requires(provider != null, null, "provider != null");
			Contract.Requires(condition != null, null, "condition != null");
			Contract.Requires(iterate != null, null, "iterate != null");
			Contract.Requires(resultSelector != null, null, "resultSelector != null");
			Contract.Requires(timeSelector != null, null, "timeSelector != null");
			Contract.Requires(scheduler != null, null, "scheduler != null");
			Contract.Ensures(Contract.Result<IQbservable<TResult>>() != null, null, "Contract.Result<IQbservable<TResult>>() != null");
			return null;
		}

		public static IQbservable<IGroupedObservable<TKey, TSource>> GroupBy<TSource, TKey>(this IQbservable<TSource> source, Expression<Func<TSource, TKey>> keySelector)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(keySelector != null, null, "keySelector != null");
			Contract.Ensures(Contract.Result<IQbservable<IGroupedObservable<TKey, TSource>>>() != null, null, "Contract.Result<IQbservable<IGroupedObservable<TKey, TSource>>>() != null");
			return null;
		}

		public static IQbservable<IGroupedObservable<TKey, TElement>> GroupBy<TSource, TKey, TElement>(this IQbservable<TSource> source, Expression<Func<TSource, TKey>> keySelector, Expression<Func<TSource, TElement>> elementSelector)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(keySelector != null, null, "keySelector != null");
			Contract.Requires(elementSelector != null, null, "elementSelector != null");
			Contract.Ensures(Contract.Result<IQbservable<IGroupedObservable<TKey, TElement>>>() != null, null, "Contract.Result<IQbservable<IGroupedObservable<TKey, TElement>>>() != null");
			return null;
		}

		public static IQbservable<IGroupedObservable<TKey, TSource>> GroupBy<TSource, TKey>(this IQbservable<TSource> source, Expression<Func<TSource, TKey>> keySelector, IEqualityComparer<TKey> comparer)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(keySelector != null, null, "keySelector != null");
			Contract.Requires(comparer != null, null, "comparer != null");
			Contract.Ensures(Contract.Result<IQbservable<IGroupedObservable<TKey, TSource>>>() != null, null, "Contract.Result<IQbservable<IGroupedObservable<TKey, TSource>>>() != null");
			return null;
		}

		public static IQbservable<IGroupedObservable<TKey, TElement>> GroupBy<TSource, TKey, TElement>(this IQbservable<TSource> source, Expression<Func<TSource, TKey>> keySelector, Expression<Func<TSource, TElement>> elementSelector, IEqualityComparer<TKey> comparer)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(keySelector != null, null, "keySelector != null");
			Contract.Requires(elementSelector != null, null, "elementSelector != null");
			Contract.Requires(comparer != null, null, "comparer != null");
			Contract.Ensures(Contract.Result<IQbservable<IGroupedObservable<TKey, TElement>>>() != null, null, "Contract.Result<IQbservable<IGroupedObservable<TKey, TElement>>>() != null");
			return null;
		}

		public static IQbservable<IGroupedObservable<TKey, TSource>> GroupByUntil<TSource, TKey, TDuration>(this IQbservable<TSource> source, Expression<Func<TSource, TKey>> keySelector, Expression<Func<IGroupedObservable<TKey, TSource>, IQbservable<TDuration>>> durationSelector)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(keySelector != null, null, "keySelector != null");
			Contract.Requires(durationSelector != null, null, "durationSelector != null");
			Contract.Ensures(Contract.Result<IQbservable<IGroupedObservable<TKey, TSource>>>() != null, null, "Contract.Result<IQbservable<IGroupedObservable<TKey, TSource>>>() != null");
			return null;
		}

		public static IQbservable<IGroupedObservable<TKey, TSource>> GroupByUntil<TSource, TKey, TDuration>(this IQbservable<TSource> source, Expression<Func<TSource, TKey>> keySelector, Expression<Func<IGroupedObservable<TKey, TSource>, IQbservable<TDuration>>> durationSelector, IEqualityComparer<TKey> comparer)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(keySelector != null, null, "keySelector != null");
			Contract.Requires(durationSelector != null, null, "durationSelector != null");
			Contract.Requires(comparer != null, null, "comparer != null");
			Contract.Ensures(Contract.Result<IQbservable<IGroupedObservable<TKey, TSource>>>() != null, null, "Contract.Result<IQbservable<IGroupedObservable<TKey, TSource>>>() != null");
			return null;
		}

		public static IQbservable<IGroupedObservable<TKey, TElement>> GroupByUntil<TSource, TKey, TElement, TDuration>(this IQbservable<TSource> source, Expression<Func<TSource, TKey>> keySelector, Expression<Func<TSource, TElement>> elementSelector, Expression<Func<IGroupedObservable<TKey, TElement>, IQbservable<TDuration>>> durationSelector)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(keySelector != null, null, "keySelector != null");
			Contract.Requires(elementSelector != null, null, "elementSelector != null");
			Contract.Requires(durationSelector != null, null, "durationSelector != null");
			Contract.Ensures(Contract.Result<IQbservable<IGroupedObservable<TKey, TElement>>>() != null, null, "Contract.Result<IQbservable<IGroupedObservable<TKey, TElement>>>() != null");
			return null;
		}

		public static IQbservable<IGroupedObservable<TKey, TElement>> GroupByUntil<TSource, TKey, TElement, TDuration>(this IQbservable<TSource> source, Expression<Func<TSource, TKey>> keySelector, Expression<Func<TSource, TElement>> elementSelector, Expression<Func<IGroupedObservable<TKey, TElement>, IQbservable<TDuration>>> durationSelector, IEqualityComparer<TKey> comparer)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(keySelector != null, null, "keySelector != null");
			Contract.Requires(elementSelector != null, null, "elementSelector != null");
			Contract.Requires(durationSelector != null, null, "durationSelector != null");
			Contract.Requires(comparer != null, null, "comparer != null");
			Contract.Ensures(Contract.Result<IQbservable<IGroupedObservable<TKey, TElement>>>() != null, null, "Contract.Result<IQbservable<IGroupedObservable<TKey, TElement>>>() != null");
			return null;
		}

		public static IQbservable<TResult> GroupJoin<TLeft, TRight, TLeftDuration, TRightDuration, TResult>(this IQbservable<TLeft> left, IObservable<TRight> right, Expression<Func<TLeft, IObservable<TLeftDuration>>> leftDurationSelector, Expression<Func<TRight, IObservable<TRightDuration>>> rightDurationSelector, Expression<Func<TLeft, IObservable<TRight>, TResult>> resultSelector)
		{
			Contract.Requires(left != null, null, "left != null");
			Contract.Requires(right != null, null, "right != null");
			Contract.Requires(leftDurationSelector != null, null, "leftDurationSelector != null");
			Contract.Requires(rightDurationSelector != null, null, "rightDurationSelector != null");
			Contract.Requires(resultSelector != null, null, "resultSelector != null");
			Contract.Ensures(Contract.Result<IQbservable<TResult>>() != null, null, "Contract.Result<IQbservable<TResult>>() != null");
			return null;
		}
	}
}